package com.hyt.it.ogt.ks.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.exception.NestedBusinessException;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.ks.enums.BizStatusCode;
import com.hyt.it.ogt.ks.enums.ExamConfigCode;
import com.hyt.it.ogt.ks.enums.PaperItemTypeCode;
import com.hyt.it.ogt.ks.enums.PushCjStatusEnum;
import com.hyt.it.ogt.ks.feign.CjClient;
import com.hyt.it.ogt.ks.feign.KwClient;
import com.hyt.it.ogt.ks.feign.KwgovCilent;
import com.hyt.it.ogt.ks.feign.PjClient;
import com.hyt.it.ogt.ks.feign.model.Exam;
import com.hyt.it.ogt.ks.feign.model.ExamDTO;
import com.hyt.it.ogt.ks.mapper.CjLogMapper;
import com.hyt.it.ogt.ks.mapper.XyEvalLogMapper;
import com.hyt.it.ogt.ks.model.cjvo.CandidateAreaVO;
import com.hyt.it.ogt.ks.model.cjvo.ExchangeCandidate;
import com.hyt.it.ogt.ks.model.cjvo.ExchangeCandidateConfig;
import com.hyt.it.ogt.ks.model.cjvo.ExchangeCandidateInfo;
import com.hyt.it.ogt.ks.model.cjvo.ExchangeStem;
import com.hyt.it.ogt.ks.model.cjvo.ExchangeSubjectInfo;
import com.hyt.it.ogt.ks.model.cjvo.MessageInfo;
import com.hyt.it.ogt.ks.model.cjvo.PaperTopicInfoDTO;
import com.hyt.it.ogt.ks.model.cjvo.SubjectInfoDTO;
import com.hyt.it.ogt.ks.model.cjvo.TaskBaseVO;
import com.hyt.it.ogt.ks.model.entity.CandidateAnswer;
import com.hyt.it.ogt.ks.model.entity.CandidateAnswerBackup;
import com.hyt.it.ogt.ks.model.entity.CandidatePaper;
import com.hyt.it.ogt.ks.model.entity.CandidateProcess;
import com.hyt.it.ogt.ks.model.entity.CjLog;
import com.hyt.it.ogt.ks.model.vo.CandidateSubjectiveScoreVO;
import com.hyt.it.ogt.ks.model.vo.ExamCandidateDetailInfoForScoreVO;
import com.hyt.it.ogt.ks.model.vo.ExamConfigVO;
import com.hyt.it.ogt.ks.model.xyvo.DayiAssessResultVO;
import com.hyt.it.ogt.ks.model.xyvo.ExamCustomizationVO;
import com.hyt.it.ogt.ks.model.xyvo.JudgeScoreVO;
import com.hyt.it.ogt.ks.model.xyvo.XyCandidateReportVO;
import com.hyt.it.ogt.ks.model.xyvo.XyEvalResultVO;
import com.hyt.it.ogt.ks.service.ExamInfoCacheService;
import com.hyt.it.ogt.ks.service.ICandidateAnswerBackupService;
import com.hyt.it.ogt.ks.service.ICandidateAnswerService;
import com.hyt.it.ogt.ks.service.ICandidatePaperService;
import com.hyt.it.ogt.ks.service.ICandidateProcessService;
import com.hyt.it.ogt.ks.service.IExamCacheService;
import com.hyt.it.ogt.ks.service.IThirdInterfaceService;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liuhh
 * @since 2020-06-02
 */
@Slf4j
@Service
public class ThirdInterfaceServiceImpl implements IThirdInterfaceService {
    @Resource
    private ICandidateAnswerService iCandidateAnswerService;
    @Resource
    private ICandidateAnswerBackupService iCandidateAnswerBackupService;
    @Resource
    private ICandidatePaperService iCandidatePaperService;
    @Resource
    private KwClient kwClient;
    @Resource
    private ICandidateProcessService iCandidateProcessService;
    @Resource
    private IExamCacheService iExamCacheService;
    @Resource
    private PjClient pjClient;
    @Resource
    private XyEvalLogMapper xyEvalLogMapper;
    @Resource
    private CjClient cjClient;
    @Resource
    private CjLogMapper cjLogMapper;
    @Resource
    private KwgovCilent kwgovCilent;
    @Resource
	private ExamInfoCacheService examInfoCacheService;

	/**
	 * 注意会存在调用接口失败，需要调用者考虑失败的处理
	 * 会存在其他第三方接口调用情况，统一写此处
	 * @param examId
	 * @param candidateId
	 */
	@Async("executor")
	@Override
	public void finishExamCallback(String examId, String candidateId) {
		try {
			// 测评的接口（针对兴业银行特殊需求，需要加权限识别，如果不是兴业银行不执行）
			//回调兴业银行考试
			this.getReportAndSendScoreDayi(examId, candidateId);
			
		} catch(Exception e) {
			log.error("考生{},回调兴业银行接口异常；" + e, candidateId);
		}
		/*
		try {
			//推送成绩到成绩系统
			this.pushScoreToCj(examId, candidateId, null, null);
		} catch(Exception e) {
			log.error("考生{},推送成绩系统接口异常；" + e, candidateId);
		}
		 */
	}	
	
	@Override
	public Boolean getReportAndSendScoreDayi(String examId, String candidateId, BigDecimal subjectiveScore) {
		LambdaQueryWrapper<CandidateProcess> queryCandidateProcess = Wrappers.lambdaQuery();
    	queryCandidateProcess.eq(CandidateProcess::getExamId, examId)
         			.eq(CandidateProcess::getCandidateId, candidateId)
         			.eq(CandidateProcess::getDelFlag, false);
    	CandidateProcess candidateProcess = iCandidateProcessService.getOne(queryCandidateProcess);
    	//获取考生信息
    	String kwCandidateInfos = kwClient.getCandidateInfos(examId, candidateId);
        log.info("调用考务系统获取考生配置信息：{}", kwCandidateInfos);
        @SuppressWarnings("unchecked")
        ApiResponse<JSONArray> kwCandidateInfosResponse = JSON.parseObject(kwCandidateInfos, ApiResponse.class);
        if (kwCandidateInfosResponse.getCode().intValue() != BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
            throw new NestedBusinessException("调用考务系统获取考生配置信息报错");
        }
        List<ExamCandidateDetailInfoForScoreVO> examCandidateDetailInfos = JSONObject.parseArray(kwCandidateInfosResponse.getData().toJSONString(), ExamCandidateDetailInfoForScoreVO.class);
        LambdaQueryWrapper<CandidatePaper> queryCandidatePaper = Wrappers.lambdaQuery();
    	queryCandidatePaper.eq(CandidatePaper::getExamId, examId)
         			.eq(CandidatePaper::getCandidateId, candidateId);
    	List<CandidatePaper> candidatePaperList = iCandidatePaperService.list(queryCandidatePaper);
    	String resultStatusCode = "200";
    	XyEvalResultVO xyEvalResult = new XyEvalResultVO();
    	Boolean requestEval = false;
    	if (!iCandidateAnswerService.isGetEvalReport(examId, candidateId)) {
        	Optional<CandidatePaper> candidatePaper = candidatePaperList.stream().filter(cpl -> cpl.getPaperType() == 2).findFirst();
        	if (candidatePaper.isPresent()) {
	        	log.info("调用测评接口请求参数：【{},{},{},{},{}】", examId, candidateId, candidatePaper.get().getPaperId(), candidatePaper.get().getPaperVersion(), examCandidateDetailInfos.toString());
	        	xyEvalResult = iCandidateAnswerService.getXyEvalResult(examId, candidateId, candidatePaper.get().getPaperId(), candidatePaper.get().getPaperVersion(), examCandidateDetailInfos);
	        	resultStatusCode = xyEvalResult.getCode();
	        	requestEval = true;
        	}
    	}
    	//if ("200".equals(resultStatusCode)) {
    		//判断是否为兴业银行考试,如果是，推送成绩给大易
    		String resXyExam = kwClient.isXyExam(examId);
    		log.info("调用考务系统获取是否为兴业银行考试：{}", resXyExam);
            @SuppressWarnings("unchecked")
            ApiResponse<Boolean> resXyExamResponse = JSON.parseObject(resXyExam, ApiResponse.class);
            if (resXyExamResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
                Boolean isXyExam = resXyExamResponse.getData();
                String resJudgeScore = kwClient.getCandidateJudgeScore(candidateId);
            	log.info("调用考务系统获取是否为兴业银行考试是否已判分：{}", resJudgeScore);
            	JudgeScoreVO judgeScore = new JudgeScoreVO();
            	@SuppressWarnings("unchecked")
                ApiResponse<JSONObject> resJudgeScoreResponse = JSON.parseObject(resJudgeScore, ApiResponse.class);
            	if (resJudgeScoreResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
            		judgeScore = JSONObject.parseObject(resJudgeScoreResponse.getData().toJSONString(), JudgeScoreVO.class);           		
            	}
                if (isXyExam && judgeScore.getFlag()) {
        			BigDecimal objectScore = candidatePaperList.stream()
            				.map(cpl -> cpl.getObjectiveScore() == null 
            				? BigDecimal.ZERO : cpl.getObjectiveScore())
            				.reduce(BigDecimal.ZERO, BigDecimal::add); 
        			BigDecimal otherScore = candidateProcess.getOtherScore() == null 
        								? BigDecimal.ZERO : candidateProcess.getOtherScore();   
        			BigDecimal totalScore = objectScore.add(otherScore).add(subjectiveScore == null ? judgeScore.getSubjectiveScore() : subjectiveScore);
            		DayiAssessResultVO dayiAssessResult = iCandidateAnswerService.sendScoreToDayi(examId, candidateId, candidateProcess.getAdmissionNumber(), totalScore, examCandidateDetailInfos);
            		return dayiAssessResult.getState() != null && dayiAssessResult.getState().intValue() == 0;
                } else {
                	if (requestEval) {
	                	XyCandidateReportVO xyCandidateReport = iCandidateAnswerService.getXyCandidateReport(xyEvalResult);
	             		xyCandidateReport.setExamId(examId);
	             		xyCandidateReport.setExamCandidateId(candidateId);
	             		kwClient.saveXyCandidateReport(JSON.toJSON(xyCandidateReport).toString());
	             		return "200".equals(resultStatusCode);
                	}
            	}
            }
    	return false;
	}
	
	@Override
	public Boolean getReportAndSendScoreDayi(String examId, String candidateId) {
		return this.getReportAndSendScoreDayi(examId, candidateId, null);
	}
	
	@Override
	public Boolean pushScoreToCj(String examId, String candidateId, List<CandidateSubjectiveScoreVO> candidateSubjectiveScoreList, CjLog cjLog) {
		//考生科目信息
		List<ExchangeSubjectInfo> subjectInfos = new ArrayList<ExchangeSubjectInfo>();
		LambdaQueryWrapper<CandidatePaper> queryCandidatePaper = Wrappers.lambdaQuery();
		queryCandidatePaper.eq(CandidatePaper::getExamId, examId)
				.eq(CandidatePaper::getCandidateId, candidateId);

		List<CandidatePaper> candidatePapers = iCandidatePaperService.list(queryCandidatePaper);
		if(candidatePapers.size() == 0) {
			return false;
		}
		
		log.info("# 调用考务获取考生试卷：{}", FastJsonUtil.getBeanToJson(candidatePapers));
		// 获取判断考生是否已判分
		String resJudgeScore = kwClient.getCandidateJudgeScore(candidateId);
     	log.info("调用考务系统获取是否为兴业银行考试是否已判分：{}", resJudgeScore);
     	JudgeScoreVO judgeScore = new JudgeScoreVO();
     	@SuppressWarnings("unchecked")
        ApiResponse<JSONObject> resJudgeScoreResponse = JSON.parseObject(resJudgeScore, ApiResponse.class);
     	if (resJudgeScoreResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
     		judgeScore = JSONObject.parseObject(resJudgeScoreResponse.getData().toJSONString(), JudgeScoreVO.class);           		
     	}
     	// 是否完成评分，只有已经判分的才推送成绩系统
     	if(judgeScore.getFlag()) {
     		if(null == cjLog) {
     			cjLog = addPushCjLog(examId, candidateId, null, null);
     		}
     		ExchangeCandidate exchangeCandidate = new ExchangeCandidate();
     		
	    	CandidateProcess candidateProcess = iCandidateProcessService.getCandidateProcessByExamIdAndCandidateId(examId, candidateId);
	    	if (null != candidateProcess && candidateProcess.getBeginTime() != null) {
	    		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	    		exchangeCandidate.setBeginTime(candidateProcess.getBeginTime().format(dtf));
	    	}	 
	    	
	    	// 获取考试信息
     		ExamDTO examDTO = examInfoCacheService.getExamInfoFromCache(examId);
     		exchangeCandidate.setExamId(examId);    		
    		exchangeCandidate.setCandidateId(candidateId);
    		
     		log.info("调用考务获取考试信息返回结果【{}】", examDTO);
            if (Objects.nonNull(examDTO)) {
                 Exam exam = examDTO.getExam();
                 exchangeCandidate.setExamName(exam.getExamName());
                 exchangeCandidate.setOfficeId(exam.getOfficeId());
                 // 如果是虚拟考场考试
                 if (StringUtils.isNotBlank(exam.getTaskId())) {
                	 exchangeCandidate.setTaskId(exam.getTaskId());
                	 String taskRes = kwgovCilent.getTaskInfo(exam.getTaskId());
                	 @SuppressWarnings("unchecked")
             		 ApiResponse<JSONObject> taskResResponse = JSON.parseObject(taskRes, ApiResponse.class);
             		 if (taskResResponse.getCode().equals(BizStatusCode.KWGOV_SUCCESS_CODE.getCode())) {
             			TaskBaseVO task = JSONObject.parseObject(taskResResponse.getData().toJSONString(), TaskBaseVO.class);
             			exchangeCandidate.setTaskName(task.getExamName());
             			exchangeCandidate.setTaskBeginDate(task.getBeginDate());
             			exchangeCandidate.setTaskEndDate(task.getEndDate());
             			exchangeCandidate.setTestClassify(task.getTestClassify());
             		 }
             		 String candidateAreaRes = kwgovCilent.getCandidateArea(exam.getTaskId(), candidateProcess.getExamId(), candidateProcess.getAdmissionNumber());
             		 @SuppressWarnings("unchecked")
             		 ApiResponse<JSONObject> candidateAreaResResponse = JSON.parseObject(candidateAreaRes, ApiResponse.class);
             		 //拉了新分支开发的，code新版成功码可能会冲突，暂时直接写进去
             		 if (candidateAreaResResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue() && candidateAreaResResponse.getData() != null) {
             			CandidateAreaVO candidateArea = JSONObject.parseObject(candidateAreaResResponse.getData().toJSONString(), CandidateAreaVO.class);
             			exchangeCandidate.setProvinceCode(candidateArea.getProvince());
             			exchangeCandidate.setCityCode(candidateArea.getCity());
             			exchangeCandidate.setCountryCode(candidateArea.getDistrict());
						exchangeCandidate.setPlaceId(candidateArea.getPlaceId());
						exchangeCandidate.setPlaceName(candidateArea.getPlaceName());
						exchangeCandidate.setTimeCandidateCounts(candidateArea.getTimeCandidateCounts());
             		 }
                 } else {
					String resCandidateCount = kwClient.getCandidateCount(examId);
					ApiResponse<Integer> resCandidateCountResponse = JSON.parseObject(resCandidateCount, ApiResponse.class);
					
					if (resCandidateCountResponse.getCode().equals(BizStatusCode.KW_SUCCESS_OK.getCode()) && resCandidateCountResponse.getData() != null) {
						exchangeCandidate.setTimeCandidateCounts(resCandidateCountResponse.getData());
					}
				 }
            }
    		
    		//获取考试信息采集
    		String resConfig = kwClient.getCandidateConfig(examId);
    		log.info("成绩推送获取考务信息采集返回结果【{}】", resConfig);
    		List<ExchangeCandidateConfig> configs = new ArrayList<ExchangeCandidateConfig>();
    		@SuppressWarnings("unchecked")
    		ApiResponse<JSONArray> resConfigResponse = JSON.parseObject(resConfig, ApiResponse.class);
    		if (resConfigResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
    			configs = JSONObject.parseArray(resConfigResponse.getData().toJSONString(), ExchangeCandidateConfig.class);
        	}		
    		exchangeCandidate.setCandidateConfig(configs);
    		
    		//获取考生信息
    		String resCandidateInfo = kwClient.getCandidateConfigInfo(examId, candidateId);
    		log.info("成绩推送获取考务考生信息返回结果【{}】", resCandidateInfo);
    		List<ExchangeCandidateInfo> candidateInfos = new ArrayList<ExchangeCandidateInfo>();
    		@SuppressWarnings("unchecked")
    		ApiResponse<JSONArray> resCandidateInfoResponse = JSON.parseObject(resCandidateInfo, ApiResponse.class);
    		if (resCandidateInfoResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
    			candidateInfos = JSONObject.parseArray(resCandidateInfoResponse.getData().toJSONString(), ExchangeCandidateInfo.class);
        	}
    		exchangeCandidate.setCandidateInfo(candidateInfos);
    		
    		List<ExamConfigVO> examConfigList = iExamCacheService.getExamConfigCache(examId);
            Optional<ExamConfigVO> examConfigPassScore = examConfigList.stream()
            		.filter(ecl -> ExamConfigCode.EXAM_CONFIG_PASS_SCORE.getCode().equals(ecl.getConfigCode()))
            		.findFirst();
            String passScore = examConfigPassScore.isPresent() ? examConfigPassScore.get().getConfigValue() : "0";
            exchangeCandidate.setScoreLine(new BigDecimal(passScore));
            //是否重做保留最高分
            Optional<ExamConfigVO> examConfigKeepHighestScore = examConfigList.stream()
            		.filter(ecl -> ExamConfigCode.EXAM_KEEP_HIGHEST_SCORE.getCode().equals(ecl.getConfigCode()))
            		.findFirst();
            Boolean keepHighestScore = examConfigKeepHighestScore.isPresent() ? "true".equals(examConfigKeepHighestScore.get().getConfigValue()): false;
            exchangeCandidate.setKeepHighestScore(keepHighestScore);

    		exchangeCandidate.setAdmissionNo(candidatePapers.get(0).getAdmissionNumber());
    		List<CandidateAnswer> candidateAnswers = new ArrayList<CandidateAnswer>();
    		if (judgeScore.getIsBackup() == 0) {
    			LambdaQueryWrapper<CandidateAnswer> queryCandidateAnswer = Wrappers.lambdaQuery();
        		queryCandidateAnswer.eq(CandidateAnswer::getExamId, examId)
        	         			.eq(CandidateAnswer::getCandidateId, candidateId);    		
        		candidateAnswers = iCandidateAnswerService.list(queryCandidateAnswer);
        		
    		} else {
    			LambdaQueryWrapper<CandidateAnswerBackup> queryCandidateAnswer = Wrappers.lambdaQuery();
        		queryCandidateAnswer.eq(CandidateAnswerBackup::getExamId, examId)
        	         			.eq(CandidateAnswerBackup::getCandidateId, candidateId);    		
        		List<CandidateAnswerBackup> candidateAnswerBackUps = iCandidateAnswerBackupService.list(queryCandidateAnswer);
        		for (CandidateAnswerBackup candidateAnswerBackup : candidateAnswerBackUps) {
        			CandidateAnswer answer = new CandidateAnswer();
                    BeanUtils.copyProperties(candidateAnswerBackup, answer);
                    candidateAnswers.add(answer);
        		}
    		}
    		//是否包含主观题
    		Boolean hasSubjcetive = false;
    		String resExistsSubjective = kwClient.isExistsSubjective(candidateId);
    		log.info("成绩推送获取考生是否包括主观题返回结果【{}】".concat(resExistsSubjective));
    		@SuppressWarnings("unchecked")
    		ApiResponse<Boolean> resExistsSubjectiveResponse = JSON.parseObject(resExistsSubjective, ApiResponse.class);
    		if (resExistsSubjectiveResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()
    				&& resExistsSubjectiveResponse.getData()) {
    			hasSubjcetive = true;
    		}
    		// 获取考生主观题得明细
    		List<CandidateSubjectiveScoreVO> subjectiveScoreListFromPj = new ArrayList<CandidateSubjectiveScoreVO>();
    	   if (hasSubjcetive) {
    		    if (candidateSubjectiveScoreList == null || candidateSubjectiveScoreList.size() == 0) {
    		    	String resStudentItemScore = pjClient.getStudentItemScore(examId, candidatePapers.get(0).getAdmissionNumber());
        			log.debug("调用评卷系统获取考生得分配置信息：{}", resStudentItemScore);
                	@SuppressWarnings("unchecked")
        			ApiResponse<JSONArray> subjectiveScoreResponse = JSON.parseObject(resStudentItemScore, ApiResponse.class);
                	if (subjectiveScoreResponse.getCode().intValue() == BizStatusCode.PJ_SUCCESS_CODE.getCode().intValue()) {
                		subjectiveScoreListFromPj = JSONObject.parseArray(subjectiveScoreResponse.getData().toString(), CandidateSubjectiveScoreVO.class);
                	} 
    		    } else {
    		    	subjectiveScoreListFromPj = candidateSubjectiveScoreList;
    		    }    			        	
    		}
    	   
    	    Long useTime = (long) 0;
    		for (CandidatePaper candidatePaper : candidatePapers) {
    			useTime += candidatePaper.getExamUseTime();
    			ExchangeSubjectInfo subjectInfo = new ExchangeSubjectInfo();
    			subjectInfo.setPaperSort(candidatePaper.getSort());  
    			subjectInfo.setPaperTimeLength(candidatePaper.getPaperTimeLength());
    			subjectInfo.setPaperUseTime(candidatePaper.getExamUseTime());
    			//获取科目信息
    			SubjectInfoDTO subjectInfoKw = new SubjectInfoDTO();
    			String resSubjectInfo = kwClient.getSubjectInfo(candidatePaper.getPaperId(), candidatePaper.getPaperVersion());
    			log.info("成绩推送获取科目信息返回结果【{}】", resSubjectInfo);
    			@SuppressWarnings("unchecked")
    			ApiResponse<JSONObject> resSubjectInfoResponse = JSON.parseObject(resSubjectInfo, ApiResponse.class);
    			if (resSubjectInfoResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
    				subjectInfoKw = JSONObject.parseObject(resSubjectInfoResponse.getData().toJSONString(), SubjectInfoDTO.class);           		
    			}	
    			subjectInfo.setSubjectCode(subjectInfoKw.getSubjectCode());
    			subjectInfo.setSubjectName(subjectInfoKw.getSubjectName());	
    			subjectInfo.setPaperFullScore(subjectInfoKw.getPaperFullScore());
    			BigDecimal paperObjectScore = candidatePaper.getObjectiveScore();
    			BigDecimal paperSubjectiveScore = BigDecimal.ZERO;

    			subjectInfo.setSubjectType(candidatePaper.getPaperType());
    			List<ExchangeStem> stemList = new ArrayList<ExchangeStem>();
    			if (candidatePaper.getPaperType().intValue() == 1 || candidatePaper.getPaperType().intValue() == 5) {
    				List<PaperTopicInfoDTO> topicInfoList = subjectInfoKw.getStemList();				
    				for (PaperTopicInfoDTO topicInfo : topicInfoList) {
    					ExchangeStem stem = new ExchangeStem();
    					BigDecimal topicScore = BigDecimal.ZERO;
    					List<CandidateAnswer> candidateAnswersForTopic = candidateAnswers.stream()
    											.filter(c -> c.getTopicId().equals(topicInfo.getStemId()) 
    													&& !(c.getItemType().equals(PaperItemTypeCode.ITEM_TYPE_COMPOUND_CODE.getCode())
    															|| (c.getItemType().equals(PaperItemTypeCode.ITEM_TYPE_FILL_IN_BLANKS_CODE.getCode()) && !c.getObjectiveOrSubjective() && StringUtils.isNotBlank(c.getParentItemId())))
    													)
    											.collect(Collectors.toList());
    					for (CandidateAnswer ca : candidateAnswersForTopic) {
    						if (ca.getObjectiveOrSubjective() && ca.getScore() != null) {
    							topicScore = topicScore.add(ca.getScore());
    						} else {
    							Optional<CandidateSubjectiveScoreVO> subjectiveScore = subjectiveScoreListFromPj.stream()
    														.filter(ss -> ca.getItemId().equals(ss.getItemId()))
    														.findFirst();
    							if (subjectiveScore.isPresent() && subjectiveScore.get().getScore() != null) {
    								topicScore = topicScore.add(subjectiveScore.get().getScore());  
    								paperSubjectiveScore = paperSubjectiveScore.add(subjectiveScore.get().getScore());
    							}
    						}
    					}    					
    					stem.setStemId(topicInfo.getStemId());
    					stem.setStemName(topicInfo.getStemName());
    					stem.setTopicSort(topicInfo.getStemSort());
    					stem.setStemScore(topicScore);
    					stemList.add(stem);
    				}
    				subjectInfo.setPapertScore(paperObjectScore.add(paperSubjectiveScore));				
    			} else if(candidatePaper.getPaperType().intValue() == 2) {
    				String resCandidateReport = kwClient.getEvalReport(examId, candidateId);
    				log.info("成绩推送获取性格测试报告返回结果【{}】", resCandidateReport);
    				 ApiResponse<String> resCandidateReportResponse = ApiResponse.ConvertRet(resCandidateReport, String.class);
    				if (resCandidateReportResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()
    						&& resCandidateReportResponse.getData() != null) {
    					String report = resCandidateReportResponse.getData().toString();
    					subjectInfo.setRemarks(report);
    				}
    			}		
    			exchangeCandidate.setUseTime(useTime);
    			subjectInfo.setStemList(stemList);
    			subjectInfos.add(subjectInfo);
    		}
    		//是否有编程题
    		String resExamCustomization = kwClient.getExamCustomization();
    		log.info("获取定制化配置返回结果【{}】", resExamCustomization);
        	@SuppressWarnings("unchecked")
    		ApiResponse<JSONArray> resResponse = JSON.parseObject(resExamCustomization, ApiResponse.class);
            if (resResponse.getCode().intValue() == BizStatusCode.KW_SUCCESS_OK.getCode().intValue()) {
            	 List<ExamCustomizationVO> examCustomizationList = JSONObject.parseArray(resResponse.getData().toString(),
    						ExamCustomizationVO.class);
    			 Optional<ExamCustomizationVO> examCustomization = examCustomizationList.stream()
    							.filter(e -> examId.equals(e.getExamId())).findFirst();
    			 if (examCustomization.isPresent() && examCustomization.get().getCodingQuestion()) {
    				 ExchangeSubjectInfo subjectInfoCoding = new ExchangeSubjectInfo();
    				 subjectInfoCoding.setSubjectCode("CODE001");
    				 subjectInfoCoding.setSubjectName("编程题");
    				 subjectInfoCoding.setSubjectType(3); 
    				 subjectInfoCoding.setPaperTimeLength(Long.parseLong("0"));//供应商编程题没有提供试卷时长
    				 subjectInfoCoding.setPaperUseTime(Long.parseLong("0"));
    				 subjectInfoCoding.setPapertScore(candidateProcess.getOtherScore());				 
    				 subjectInfos.add(subjectInfoCoding);
    			 }
            }
    		
    		exchangeCandidate.setSubjectInfo(subjectInfos);
    		log.info("推送给成绩系统请求参数【{}】", exchangeCandidate.toString());
    		MessageInfo messageInfo = new MessageInfo();
    		messageInfo.setMsg(JSON.toJSONString(exchangeCandidate));
    		String resPushCj = cjClient.saveCandidateInfo(messageInfo);
    		log.info("推送给成绩系统返回结果：【{}】", resPushCj);
    		updatePushCjLog(cjLog, exchangeCandidate, resPushCj);
    		return true;
     	}
     	return false;
	}

	/***
	 * 更新记录状态
	 * @param cjLog
	 * @param exchangeCandidate
	 * @param resPushCj
	 */
	private void updatePushCjLog(CjLog cjLog, ExchangeCandidate exchangeCandidate, String resPushCj) {
		
		if (StringUtils.isNotEmpty(resPushCj)) {
			try {
				JSONObject jsonObject = JSON.parseObject(resPushCj);
				Integer code = jsonObject.getInteger("code");
				if (null != code && Integer.valueOf(200).equals(code)) {
					cjLog.setPushCjStatus(PushCjStatusEnum.FINISH.getStatus());
				} else {
					cjLog.setPushCjStatus(PushCjStatusEnum.FAIL.getStatus());
				}
			} catch (Exception e) {
				e.printStackTrace();
				cjLog.setPushCjStatus(PushCjStatusEnum.FAIL.getStatus());
			}
			
		}else {
			cjLog.setPushCjStatus(PushCjStatusEnum.FAIL.getStatus());
		}
		if(null != exchangeCandidate) {
			cjLog.setRequestJson(JSON.toJSONString(exchangeCandidate));
		}
		cjLog.setResultData(resPushCj);
		cjLog.setCreateDate(LocalDateTime.now());
		cjLogMapper.updateById(cjLog);
		
	}

	private CjLog addPushCjLog(String examId, String candidateId, ExchangeCandidate exchangeCandidate, String resPushCj) {
		CjLog cjLog = new CjLog();
		cjLog.setId(UUIDUtils.randomUUID());
		cjLog.setExamId(examId);
		cjLog.setPushCjStatus(PushCjStatusEnum.INIT.getStatus());
		cjLog.setCandidateId(candidateId);
		if(null != exchangeCandidate) {
			cjLog.setRequestJson(JSON.toJSONString(exchangeCandidate));
		}
		cjLog.setResultData(resPushCj);
		cjLog.setCreateDate(LocalDateTime.now());
		cjLogMapper.insert(cjLog);
		return cjLog;
	}
}
